package cn.bigfire.wzdj.util.sign;

import cn.bigfire.wzdj.pojo.httpVo.HttpLoginResult;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import io.netty.util.internal.ThrowableUtil;
import lombok.SneakyThrows;
import net.dongliu.requests.Requests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.TreeMap;

public class WZDJAppSign {

    private static final Logger log = LoggerFactory.getLogger(WZDJAppSign.class);

    public static HttpLoginResult loginByAccount(String accountText, String passwordText){
        try {
            String uuid = SECRET_KEY;//
            //明文密码 需要加密
            String account = encrypt(accountText,uuid);
            String password = encrypt(passwordText,uuid);
            //bodyMap
            TreeMap<String,String> bodyMap = new TreeMap<>();
            bodyMap.put("account", account);
            bodyMap.put("password", password);
            //paramMap
            String timestamp = (System.currentTimeMillis() / 1000)+"";
//        String uuid = "wx-ol9sW7RiscrRqWOQ1wPrQSP0NKEM";//用户wx- openId
            TreeMap<String,String> paramMap = new TreeMap<>();
            paramMap.put("appid", "2074");
            paramMap.put("clienttype", "2");
            paramMap.put("encryptflag", "4");
            paramMap.put("isencrypt", "1");
            paramMap.put("pid", "2074600");
            paramMap.put("timestamp", timestamp);
            paramMap.put("uuid", uuid);
            //sign
            TreeMap<String,String> signMap = new TreeMap<>(paramMap);
            signMap.put("body", JSON.toJSONString(bodyMap));
            String sign = sign(signMap);
            //sign 重新放回参数中
            paramMap.put("sign", sign);
            //请求头
            HashMap<String, String> headers = new HashMap<>();
            headers.put("User-Agent", "Dalvik/2.1.0 (Linux; U; Android 10; SKR-A0 MIUI/V11.0.4.0.JOYUI)");
            headers.put("Content-Type", "application/json");
            headers.put("idcardlockedversion", "3.8.2.2404");
            headers.put("authorization", "Bearer");
            headers.put("content-type", "application/json; charset=utf-8");
            //url参数，请求头，请求body，一把梭。发请求
            String wxLoginApi = "https://sdkapi.hnys68.cn/api/sdk/v2/accounts/action/registerlogin/account";
            String readToText = Requests.post(wxLoginApi).params(paramMap).headers(headers).body(JSON.toJSONString(bodyMap)).send().readToText();
            log.info("api:{}", wxLoginApi);
            log.info("result:{}",readToText);
            if (JSONUtil.isTypeJSONObject(readToText)) {
                HttpLoginResult httpLoginResult = JSON.parseObject(readToText, HttpLoginResult.class);
                return httpLoginResult;
            } else {
                log.error(readToText);
            }
        } catch (Exception e) {
            log.error("loginByAccount has error:" + ThrowableUtil.stackTraceToString(e));
        }
        return null;
    }

    /**
     * encrypt 加密   AES/ECB/NoPadding   key 为 uuid    安卓base64  url编码
     *
     * @param plaintext 明文数据
     * @param uuid 加密的key 用uuid就行了
     * @return String 加密后的 账号｜密码
     */
    @SneakyThrows
    public static String encrypt(String plaintext,String uuid){
        //明文数据填充到16的整数倍数据
        byte[] paddedData = padTo16(plaintext);
        //AES/ECB/NoPadding   加密 key = uuid
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(uuid.getBytes(), "AES"));
        byte[] encryptData = cipher.doFinal(paddedData);
        //安卓一样的base64
        String androidBase64 = Base64.getEncoder().encodeToString(encryptData);
        //url编码
        return URLEncodeUtil.encode(androidBase64);
    }

    /**
     * 文本填充16位
     *
     * @param text 原文本
     * @return byte[] 补充0后的数据
     */
    @SneakyThrows
    public static byte[] padTo16(String text) {
        // AES 块大小为 16 字节
        int blockSize = 16;
        byte[] bytesData = text.getBytes("UTF-8");
        int length = bytesData.length;
        // 检查数据长度是否是块大小的倍数
        if (length % blockSize!= 0) {
            int paddingLength = blockSize - (length % blockSize);
            byte[] paddingBytes = new byte[paddingLength];
            // 填充 0 字节
            for (int i = 0; i < paddingLength; i++) {
                paddingBytes[i] = 0;
            }
            byte[] newBytesData = new byte[length + paddingLength];
            System.arraycopy(bytesData, 0, newBytesData, 0, length);
            System.arraycopy(paddingBytes, 0, newBytesData, length, paddingLength);
            return newBytesData;
        }
        return bytesData;
    }

    //签名，（排序，拼接，sha256）
    public static String SECRET_KEY = "d01474ee9670540687a7f2464a570abc";//不变key
    public static String sign(TreeMap<String,String> signMap){
        String str = MapUtil.sortJoin(signMap, "&", "=", true);
        return SecureUtil.hmacSha256(SECRET_KEY).digestHex(str);
    }
}
